package com.settlement.system.handler.disruptor;

import com.alibaba.fastjson2.JSONObject;
import com.settlement.system.common.constant.KafkaConstants;
import com.settlement.system.common.constant.SystemConstants;
import com.settlement.system.common.enums.BillCheckStatusEnum;
import com.settlement.system.common.enums.DataGenerationEnum;
import com.settlement.system.common.enums.DeleteEnum;
import com.settlement.system.common.model.Option;
import com.settlement.system.common.util.DateUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.mapper.SysOrderDetailMapper;
import com.settlement.system.model.entity.*;
import com.settlement.system.model.vo.BsOmsOrderImportVo;
import com.settlement.system.model.vo.BsOmsReturnOrderImportVo;
import com.settlement.system.model.vo.SysOrderDetailImportVo;
import com.settlement.system.service.*;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.apache.ibatis.ognl.Ognl;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.support.Acknowledgment;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class KafkaConsumer {

    private final static Logger logger = LoggerFactory.getLogger(KafkaConsumer.class);

    private final SysStoreService storeService;
    private final SysPlatformService platformService;
    private final PlatformSourceDataService platformSourceDataService;
    private final SysBillService sysBillService;
    private final SysOrderService sysOrderService;
    private final SysColumnMatchService sysColumnMatchService;
    private final SysBaseColumnMatchService sysBaseColumnMatchService;
    private final SysAuditService sysAuditService;
    private final SysImportErrorDetailService sysImportErrorDetailService;
    private final SysOrderDetailMapper sysOrderDetailMapper;
    private final RedisTemplate redisTemplate;
    private final KafkaConsumeRecordService kafkaConsumeRecordService;

    private final NoMatchRecordService noMatchRecordService;

    private final SnowflakeIdWorker snowflakeIdWorker = SnowflakeIdWorker.getInstance();

    @Value("${system.config.check-original-data}")
    private Boolean checkOriginalData;

    // 监听订单的消息队列
    @KafkaListener(id = KafkaConstants.HWG_TOPIC_ORDER_QUEUE, topics = KafkaConstants.HWG_TOPIC_ORDER_QUEUE, groupId = "yzConsumerGroup", topicPartitions = {}, concurrency = "4")
    public void topicOrderQueue(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment) {
        logger.info("【standard-order-queue】当前消费者本次拉取的数据量为：{}", (Objects.isNull(records) ? 0 : records.size()));
        if (Objects.isNull(records) || records.isEmpty()) {
            logger.error("【standard-order-queue】无消费数据...");
        }
        String platformAndType = "标准订单转换队列";
        for (ConsumerRecord<String, String> record : records) {
            String message = record.value();
            String dataId = null;
            try {
                MessageVo messageVo = JSONObject.parseObject(message, MessageVo.class);
                logger.info("监听订单的消息队列开始消费：" + messageVo.getDataMap().get("pId"));
                // 订单或者售后单以平台唯一ID为标准
                dataId = messageVo.getDataMap().get("pId");
                // 检查消息队列是否消费过
                boolean canConsume = kafkaConsumeRecordService.checkCanConsume(dataId);
                logger.info("检查数据【%s】能否消费，检查结果：【%s】".formatted(dataId, canConsume));
                if (canConsume) {
                    this.omsFunc(messageVo);
                    logger.info("保存消费记录：【%s】".formatted(dataId));
                    kafkaConsumeRecordService.saveData(dataId);
                } else {
                    // 已经消费过，需要把失败提示记录标记删除
                    sysImportErrorDetailService.deleteRecord(platformAndType, dataId);
                }
            } catch (Exception e) {
                logger.info("监听订单的消息队列消费异常：" + e.getMessage());
                SysImportErrorDetail detail = new SysImportErrorDetail();
                // 平台唯一ID
                detail.setOrderNo(dataId);
                detail.setPlatformAndType(platformAndType);
                detail.setQueueName(KafkaConstants.HWG_TOPIC_ORDER_QUEUE);
                detail.setDataText(message);
                detail.setRemark(e.getMessage());
                sysImportErrorDetailService.checkAndCreate(detail);
            }
            logger.info("监听订单的消息队列结束消费：" + message);
        }
        // 手动提交
        acknowledgment.acknowledge();
    }

    // 监听账单的消息队列
    @KafkaListener(id = KafkaConstants.HWG_TOPIC_BILL_QUEUE, topics = KafkaConstants.HWG_TOPIC_BILL_QUEUE, groupId = "yzConsumerGroup", topicPartitions = {}, concurrency = "4")
    public void topicBillQueue(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment) {
        logger.info("【standard-bill-queue】当前消费者本次拉取的数据量为：{}", (Objects.isNull(records) ? 0 : records.size()));
        if (Objects.isNull(records) || records.isEmpty()) {
            logger.error("【standard-bill-queue】无消费数据...");
        }
        String dataId = null;
        String platformAndType = "标准账单转换队列";
        for (ConsumerRecord<String, String> record : records) {
            String message = record.value();
            logger.info("监听账单的消息队列开始消费：" + message);
            try {
                MessageVo messageVo = JSONObject.parseObject(message, MessageVo.class);
                dataId = messageVo.getDataId();
                // 检查消息队列是否消费过
                boolean canConsume = kafkaConsumeRecordService.checkCanConsume(messageVo.getDataId());
                logger.info("检查数据【%s】能否消费，检查结果：【%s】".formatted(messageVo.getDataId(), canConsume));
                if (canConsume) {
                    boolean hasSourceBill = true;
                    if (Objects.nonNull(checkOriginalData) && checkOriginalData) {
                        hasSourceBill = platformSourceDataService.existDataByTableNameAndId(messageVo.getTableNamePrefix() + messageVo.getDataId().substring(0, 6), messageVo.getDataId());
                        logger.info("检查原始账单是否存在：【{}】", hasSourceBill);
                    }
                    if (hasSourceBill) {
                        boolean canTransferToBill = this.billFunc(messageVo);
                        logger.info("检查是否可以生成kafka消费记录：【%s】".formatted(canTransferToBill));
                        if (canTransferToBill) {
                            logger.info("保存消费记录：【%s】".formatted(messageVo.getDataId()));
                            kafkaConsumeRecordService.saveData(messageVo.getDataId());
                        }
                    } else {
                        logger.info("检查原始账单【{}】已被删除...", messageVo.getDataId());
                        sysImportErrorDetailService.deleteRecord(platformAndType, dataId);
                    }
                } else {
                    // 已经消费过，需要把失败提示记录标记删除
                    sysImportErrorDetailService.deleteRecord(platformAndType, dataId);
                    if (Objects.nonNull(messageVo.getNoMatchRecordId())) {
                        logger.info("已经消费过，删除账单未匹配记录：【{}】", messageVo.getNoMatchRecordId());
                        NoMatchRecord noMatchRecord = noMatchRecordService.getById(messageVo.getNoMatchRecordId());
                        noMatchRecord.setDeleted(DeleteEnum.YES.getValue());
                        noMatchRecordService.updateById(noMatchRecord);
                    }
                    // 修改原始账单为转换成功，以便后面失败可以重试
                    platformSourceDataService.updateSourceStatus(messageVo.getTableNamePrefix(), messageVo.getBillMonth(), messageVo.getDataId());
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("监听账单的消息队列消费异常：" + e.getMessage());
                SysImportErrorDetail detail = new SysImportErrorDetail();
                detail.setOrderNo(dataId);
                detail.setPlatformAndType(platformAndType);
                detail.setQueueName(KafkaConstants.HWG_TOPIC_BILL_QUEUE);
                detail.setDataText(message);
                detail.setRemark(e.getMessage());
                sysImportErrorDetailService.checkAndCreate(detail);
            }
            logger.info("监听账单的消息队列结束消费：" + message);
        }
        // 手动提交
        acknowledgment.acknowledge();
    }


    @KafkaListener(id = KafkaConstants.HWG_TOPIC_FIX_BILL_QUEUE, topics = KafkaConstants.HWG_TOPIC_FIX_BILL_QUEUE, groupId = "yzConsumerGroup", topicPartitions = {}, concurrency = "4")
    public void topicFixBillQueue(List<ConsumerRecord<String, String>> records, Acknowledgment acknowledgment) {
        if (Objects.isNull(records) || records.isEmpty()) {
            logger.error("无消费数据...");
        }
        String dataId = null;
        String platformAndType = "标准账单转换队列";
        for (ConsumerRecord<String, String> record : records) {
            String message = record.value();
            logger.info("监听账单的消息队列开始消费：" + message);
            try {
                MessageVo messageVo = JSONObject.parseObject(message, MessageVo.class);
                dataId = messageVo.getDataId();
                // 检查消息队列是否消费过
                boolean canConsume = kafkaConsumeRecordService.checkCanConsume(messageVo.getDataId());
                logger.info("检查数据【%s】能否消费，检查结果：【%s】".formatted(messageVo.getDataId(), canConsume));
                if (canConsume) {
                    boolean hasSourceBill = true;
                    if (Objects.nonNull(checkOriginalData) && checkOriginalData) {
                        hasSourceBill = platformSourceDataService.existDataByTableNameAndId(messageVo.getTableNamePrefix() + messageVo.getDataId().substring(0, 6), messageVo.getDataId());
                        logger.info("检查原始账单是否存在：【{}】", hasSourceBill);
                    }
                    if (hasSourceBill) {
                        boolean canTransferToBill = this.billFunc(messageVo);
                        logger.info("检查是否可以生成kafka消费记录：【%s】".formatted(canTransferToBill));
                        if (canTransferToBill) {
                            logger.info("保存消费记录：【%s】".formatted(messageVo.getDataId()));
                            kafkaConsumeRecordService.saveData(messageVo.getDataId());
                        }
                    } else {
                        logger.info("检查原始账单【{}】已被删除...", messageVo.getDataId());
                        sysImportErrorDetailService.deleteRecord(platformAndType, dataId);
                    }
                } else {
                    // 已经消费过，需要把失败提示记录标记删除
                    sysImportErrorDetailService.deleteRecord(platformAndType, dataId);
                    if (Objects.nonNull(messageVo.getNoMatchRecordId())) {
                        logger.info("已经消费过，删除账单未匹配记录：【{}】", messageVo.getNoMatchRecordId());
                        NoMatchRecord noMatchRecord = noMatchRecordService.getById(messageVo.getNoMatchRecordId());
                        noMatchRecord.setDeleted(DeleteEnum.YES.getValue());
                        noMatchRecordService.updateById(noMatchRecord);
                    }
                    // 修改原始账单为转换成功，以便后面失败可以重试
                    platformSourceDataService.updateSourceStatus(messageVo.getTableNamePrefix(), messageVo.getBillMonth(), messageVo.getDataId());
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("监听账单的消息队列消费异常：" + e.getMessage());
                SysImportErrorDetail detail = new SysImportErrorDetail();
                detail.setOrderNo(dataId);
                detail.setPlatformAndType(platformAndType);
                detail.setQueueName(KafkaConstants.HWG_TOPIC_BILL_QUEUE);
                detail.setDataText(message);
                detail.setRemark(e.getMessage());
                sysImportErrorDetailService.checkAndCreate(detail);
            }
            logger.info("监听账单的消息队列结束消费：" + message);
        }
        // 手动提交
        acknowledgment.acknowledge();
    }

    private static final Pattern linePattern = Pattern.compile("_(\\w)");

    /**
     * 下划线转驼峰
     */
    public static String lineToHump(String str) {
        str = str.toLowerCase();
        Matcher matcher = linePattern.matcher(str);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 通过数据库ID获取出账日期的值
     *
     * @param outBillConfig          基础配置里的出账日期配置
     * @param sourceTableDataMapList 原始数据库数据
     * @param dictList               字典数据(key 中文数据库名称， value 数据库英文字段名称)
     * @param dbId                   数据库ID
     * @return 出账日期
     */
    private LocalDateTime getOutBillDateFromSourceTableDataMap(SysBaseColumnMatch outBillConfig, List<Map<String, Object>> sourceTableDataMapList, List<Option> dictList, String dbId) {
        for (Map<String, Object> stringObjectMap : sourceTableDataMapList) {
            // 找到对应的记录
            if (Objects.equals(stringObjectMap.get("id").toString(), dbId)) {
                // 通过字典中文名称获取英文字段名称
                String sourceColumnCn = outBillConfig.getSourceColumn();
                Option option = dictList.stream().filter(item -> item.getLabel().equals(sourceColumnCn)).findFirst().get();
                // 再通过英文字段名称获取数据库字段的值
                return DateUtils.convertStringToLocalDateTime(stringObjectMap.get(option.getValue()).toString());
            }
        }
        return null;
    }

    /**
     * 根据不同的单据类型，累计原始字段的值
     *
     * @param sourceTableDataMap  原始账单的数据库中的数据Map
     * @param dictListMap         原始账单的字典数据列表
     * @param calculateColumnList 需要计算的原始账单配置
     * @return 累计结果
     */
    private ResultObj sumColumnValueFromConfig(Map<String, List<Map<String, Object>>> sourceTableDataMap, Map<String, List<Option>> dictListMap, List<SysCalculateColumn> calculateColumnList, List<SysBaseColumnMatch> sysBaseColumnMatches) {
        ResultObj returnObj = new ResultObj();
        BigDecimal total = BigDecimal.ZERO;
        BigDecimal subTotal;
        ResultObj resultObj;
        // 取最晚或者最早的出账日期
        LocalDateTime lastOutBillDate = null;
        // 循环处理每一个配置
        if (calculateColumnList != null && calculateColumnList.size() > 0) {
            // 需要计算的项，循环处理每一个计算的配置
            for (SysCalculateColumn calculateColumn : calculateColumnList) {
                resultObj = new ResultObj();
                // 通过配置和条件，找到原始账单的字段对应的值
                SysBaseColumnMatch outBillConfig = sysBaseColumnMatches.stream().filter(item -> Objects.equals(item.getBillType(), calculateColumn.getBillType()) && Objects.equals(item.getStandardColumn(), SystemConstants.OUT_BILL_DATE)).findFirst().get();
                getColumnValueFromConfig(sourceTableDataMap, dictListMap, calculateColumn.getBillType(), calculateColumn.getSourceColumn(), calculateColumn.getConditions(), resultObj, outBillConfig.getSourceColumn());
                if (resultObj.getResultList().size() == 0) {
                    continue;
                }
                if (Objects.isNull(lastOutBillDate)) {
                    lastOutBillDate = resultObj.getOutBillDate();
                } else if (resultObj.getOutBillDate().isAfter(lastOutBillDate)) {
                    lastOutBillDate = resultObj.getOutBillDate();
                }
                if (Objects.nonNull(lastOutBillDate)) {
                    // 追加所有的出账日期
                    returnObj.getOutBillDateList().add(lastOutBillDate);
                }
                subTotal = resultObj.getResultList().stream().map(item -> new BigDecimal(item).abs()).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
                if ("+".equalsIgnoreCase(calculateColumn.getCalculateRule().strip())) {
                    total = total.add(subTotal);
                } else {
                    total = total.subtract(subTotal);
                }
            }
        }
        returnObj.setTotalAmount(total);
        returnObj.setOutBillDate(lastOutBillDate);
        return returnObj;
    }

    /**
     * 通过原始账单的字典数据列表，找到原始账单的字段对应的值
     *
     * @param sourceTableDataMap 原始账单的数据库中的数据Map
     * @param dictListMap        原始账单的字典数据列表
     * @param billType           原始账单类型
     * @param sourceColumn       原始账单的字段
     * @param conditions         符合条件
     * @return 原始账单的字段对应的值
     */
    private void getColumnValueFromConfig(Map<String, List<Map<String, Object>>> sourceTableDataMap, Map<String, List<Option>> dictListMap, String billType, String sourceColumn, List<SysColumnMatchCondition> conditions, ResultObj resultObj, String outBillCn) {
        // 找到字典数据，中文对应数据库英文字段
        List<Option> optionList = dictListMap.get(billType);
        Option option = optionList.stream().filter(item -> Objects.equals(item.getLabel().strip(), sourceColumn.strip())).findFirst().orElse(null);
        if (Objects.isNull(option)) {
            return;
        }
        // 如果有条件，判断条件
        if (conditions != null && conditions.size() > 0) {
            // 只取第一条来判断表达式，其他忽略
            checkIsValid(conditions.get(0).getConditions(), conditions.get(0).getParams(), sourceTableDataMap, dictListMap, resultObj, billType, option, optionList, outBillCn);
        } else {
            // 没有条件，直接取值
            getValueDirect(sourceTableDataMap, resultObj, billType, option, optionList, outBillCn);
        }
    }

    /**
     * 没有条件，直接通过原始账单的字典数据列表，找到原始账单的字段对应的值
     *
     * @param sourceTableDataMap 原始账单的数据库中的数据Map
     * @param resultObj          结果对象
     * @param billType           原始账单类型
     * @param option             需要取值的中英文配置对象
     * @param optionList         通过这个中英文配置找到出账日期配置
     */
    private void getValueDirect(Map<String, List<Map<String, Object>>> sourceTableDataMap, ResultObj resultObj, String billType, Option option, List<Option> optionList, String outBillCn) {
        List<Map<String, Object>> mapDataList = sourceTableDataMap.get(billType);
        if (Objects.isNull(mapDataList) || mapDataList.size() == 0) {
            return;
        }
        String columnEn = option.getValue().toString();
        for (Map<String, Object> stringObjectMap : mapDataList) {
            if (Objects.isNull(stringObjectMap)) {
                continue;
            }
            if (stringObjectMap.containsKey(columnEn)) {
                // 追加金额对象
                resultObj.getResultList().add(stringObjectMap.get(columnEn).toString());
                // 追加对应的数据库表ID
                resultObj.getResultIdList().add(stringObjectMap.get("id").toString());
                if (Objects.isNull(outBillCn)) {
                    return;
                }
                // 找到出账日期
                Option outBillDateOption = optionList.stream().filter(item -> Objects.equals(item.getLabel(), outBillCn)).findFirst().orElse(null);
                if (Objects.nonNull(outBillDateOption)) {
                    LocalDateTime time = DateUtils.convertStringToLocalDateTime(stringObjectMap.get(outBillDateOption.getValue().toString()).toString());
                    resultObj.setOutBillDate(time);
                    resultObj.getOutBillDateList().add(time);
                }
            }
        }
    }

    private LocalDateTime getBusinessDateFromSourceTableDataMap(SysBaseColumnMatch baseColumnMatch,
                                                                Map<String, List<Map<String, Object>>> sourceTableDataMap,
                                                                Map<String, List<Option>> dictListMap) {
        // 原始表名
        String billType = baseColumnMatch.getBillType();
        // 原始字段名称
        String sourceColumn = baseColumnMatch.getSourceColumn();
        // 原始表名的所有数据库字段列表
        List<Option> options = dictListMap.get(billType);
        Option option = options.stream().filter(item -> item.getLabel().equals(sourceColumn))
                .findFirst().orElse(null);
        // 从数据库通过sql语句查询出来的数据集
        List<Map<String, Object>> stringObjectMap = sourceTableDataMap.get(billType);
        if (Objects.isNull(stringObjectMap) || stringObjectMap.size() == 0) {
            return null;
        }
        List<Option> optionList = dictListMap.get(billType);
        // 比较条件
        List<SysColumnMatchCondition> conditions = baseColumnMatch.getConditions();
        // 比较所有的数据库值，是否符合条件
        boolean valid;
        for (Map<String, Object> objectMap : stringObjectMap) {
            String columnEn = option.getValue().toString();
            Object valueObj = objectMap.get(columnEn);
            valid = checkConditionIsValid(conditions, objectMap, optionList);
            if (valid && Objects.nonNull(valueObj)) {
                try {
                    return (LocalDateTime) valueObj;
                } catch (Exception e) {
                    logger.error("转换日期类型失败，尝试通过工具类转换：【%s】".formatted(valueObj.toString()));
                    return DateUtils.convertStringToLocalDateTime(valueObj.toString());
                }
            }
        }
        return null;
    }

    private boolean checkConditionIsValid(List<SysColumnMatchCondition> conditions, Map<String, Object> sourceTableDataMap, List<Option> optionList) {
        if (Objects.isNull(conditions) || conditions.size() == 0) {
            return true;
        }
        boolean isValid;
        for (SysColumnMatchCondition condition : conditions) {
            String conditionText = condition.getConditions();
            String params = condition.getParams();
            isValid = checkConditionIsValidFunc(conditionText, params, sourceTableDataMap, optionList);
            if (isValid) {
                return true;
            }
        }
        return false;
    }

    private boolean checkConditionIsValidFunc(String conditionText, String params, Map<String, Object> sourceTableDataMap, List<Option> optionList) {
        if (Objects.isNull(conditionText) || Objects.isNull(params) || Objects.isNull(sourceTableDataMap)) {
            return false;
        }
        String[] strings;
        Option option;
        String dbValue;
        Map<String, Object> context = new HashMap<>();
        for (String param : params.split(",")) {
            try {
                if (!StringUtils.hasText(param.strip())) {
                    continue;
                }
                strings = param.split("的", 2);
                String tableFieldCn = strings[1].strip();
                option = optionList.stream().filter(item -> item.getLabel().equals(tableFieldCn))
                        .findFirst()
                        .orElse(null);
                if (Objects.isNull(option)) {
                    return false;
                }
                if (Objects.nonNull(sourceTableDataMap.get(option.getValue()))) {
                    dbValue = sourceTableDataMap.get(option.getValue()).toString();
                } else {
                    return false;
                }
                context.put(param.strip().replaceAll("/", ""), dbValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            if (context.isEmpty()) {
                return false;
            }
            conditionText = conditionText.replaceAll("/", "");
            return (Boolean) Ognl.getValue(conditionText.strip().replaceAll("“", "\"").replaceAll("”", "\""), context);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 转换标准账单的过程，返回是否成功转换的标记
     *
     * @param messageVo 账单数据结构
     * @return 转换标记
     */
    private boolean billFunc(MessageVo messageVo) {
        // 店铺
        SysStore sysStore = storeService.getById(messageVo.getStoreId());
        // 平台
        SysPlatform sysPlatform = platformService.getByPlatformKey(sysStore.getStoreKey());
        // 再通过数据ID获取账单月份，得到需要查询的表名
        String tableName = messageVo.getTableNamePrefix() + messageVo.getDataId().substring(0, 6);
        // 通过表名用任何一个Service去查找数据，先用一个Map字典缓存数据
        Map<String, Object> dataMap = platformSourceDataService.getDataByTableNameAndId(tableName, messageVo.getDataId());
        for (String key : dataMap.keySet()) {
            // 替换空值
            if (Objects.isNull(dataMap.get(key))) {
                dataMap.put(key, "");
            }
        }
        // 临时变量
        List<Map<String, Object>> mapList;
        // 再通过单据类型去查字典，找到对应的表名
        Map<String, List<Map<String, Object>>> sourceTableDataMap = new HashMap<>();
        List<Option> dictList = platformService.getDictListFromDictType(messageVo.getDictCode());
        // 取得关联单号的值
        SysDictType sysDictType = platformService.getSysDictTypeByDictCode(messageVo.getDictCode());
        // 通过字典类型找到原始账单单据类型
        String billType = sysDictType.getName().strip();
        // 添加数据到Map
        List<Map<String, Object>> dataMapList = new ArrayList<>();
        dataMapList.add(dataMap);
        sourceTableDataMap.put(billType, dataMapList);
        // 查询明细，如果有明细，需要一起查询出来
        String subTable = messageVo.getTableNamePrefix() + "detail_" + messageVo.getBillMonth();
        String sqlText = "select * from " + subTable + " where order_id = '" + messageVo.getDataId() + "'";
        mapList = platformSourceDataService.getDataBySql(sqlText, subTable);
        if (Objects.nonNull(mapList) && mapList.size() > 0) {
            dataMap = mapList.get(0);
            if (Objects.nonNull(dataMap) && dataMap.size() > 0 && Objects.nonNull(dataMap.get("id")) && dataMap.get("id").toString().length() > 0) {
                // 删除明细ID
                dataMap.remove("id");
                List<Map<String, Object>> oldMapList = sourceTableDataMap.get(billType);
                for (String key : dataMap.keySet()) {
                    // 替换空值
                    if (Objects.isNull(dataMap.get(key))) {
                        dataMap.put(key, "");
                    }
                }
                // 将明细数据添加到主数据集
                oldMapList.get(0).putAll(dataMap);
            }
        }
        // 通过平台找到账单字段配置
        List<SysBaseColumnMatch> sysBaseColumnMatches = sysBaseColumnMatchService.getByPlatform(sysPlatform.getPlatformKey() + "bill");
        // 过滤出不是业务日期或者关联单号或者出账日期或者直接计算的配置
        List<SysBaseColumnMatch> directList = sysBaseColumnMatches.stream()
                .filter(item -> Objects.equals(item.getBillType(), billType) && !SystemConstants.LINK_NO.equals(item.getStandardColumn()) && !SystemConstants.BUSINESS_DATE.equals(item.getStandardColumn()) && !SystemConstants.OUT_BILL_DATE.equals(item.getStandardColumn()) && DataGenerationEnum.DIRECT.getValue().equals(item.getDataGeneration())).toList();
        // 一个临时变量，存储直接取值的配置
        Map<String, CommonItem> commonMap = new HashMap<>();
        // 设置账单类型
        if (directList.size() > 0) {
            String sourceEn;
            String standardCn;
            String standardEn;
            CommonItem commonItem;
            // 实际只有一条
            Map<String, Object> dbMap = sourceTableDataMap.get(billType).get(0);
            for (SysBaseColumnMatch baseColumnMatch : directList) {
                sourceEn = dictList.stream().filter(item -> Objects.equals(baseColumnMatch.getSourceColumn(), item.getLabel())).findFirst().get().getValue().toString();
                if (Objects.nonNull(dbMap.get(sourceEn)) && StringUtils.hasText(dbMap.get(sourceEn).toString())) {
                    // 保存时，转成驼峰
                    standardCn = baseColumnMatch.getStandardColumn();
                    standardEn = SysBill.getColumnMap().get(standardCn);
                    commonItem = new CommonItem();
                    commonItem.setValue(dbMap.get(sourceEn).toString());
                    commonItem.setBillType(baseColumnMatch.getBillType());
                    commonMap.put(standardEn, commonItem);
                }
            }
        }
        // 找到关联单号的配置
        SysBaseColumnMatch sysBaseColumnMatch = sysBaseColumnMatches.stream()
                .filter(item -> Objects.equals(item.getBillType(), billType) && SystemConstants.LINK_NO.equals(item.getStandardColumn()))
                .findFirst().orElse(null);
        Assert.isTrue(Objects.nonNull(sysBaseColumnMatch), "单据类型【%s】【关联单号】字段配置不存在".formatted(billType));
        // 通过原始账单中文字段名找到原始账单英文字段名
        Option option = dictList.stream().filter(item -> sysBaseColumnMatch.getSourceColumn().equals(item.getLabel())).findFirst().orElse(null);
        Assert.isTrue(Objects.nonNull(option), "单据类型【%s】的字典数据【%s】不存在".formatted(billType, sysBaseColumnMatch.getSourceColumn()));
        String linkNoValue = (String) (sourceTableDataMap.get(billType).get(0)).get(option.getValue());
        // 取出所有的关联单号的配置
        List<SysBaseColumnMatch> LinkNoMatchList = sysBaseColumnMatches.stream()
                .filter(item -> SystemConstants.LINK_NO.equals(item.getStandardColumn().strip())).toList();
        // 一堆临时变量
        StringBuilder tableNamePrefix;
        String sourceColumnEn;
        List<String> billMonthList;
        Map<String, List<Option>> dictListMap = new HashMap<>();
        // 临时变量
        List<Map<String, Object>> tempMapList;
        // 循环处理关联单号的配置
        for (SysBaseColumnMatch linkNoConfig : LinkNoMatchList) {
            // 查出表名前缀
            sysDictType = platformService.getSysDictTypeByDictName(linkNoConfig.getBillType().strip());
            // 通过字段绑定关系取得关联单号的英文字段名
            String sourceColumnCn = linkNoConfig.getSourceColumn().strip();
            dictList = platformService.getDictListFromDictType(sysDictType.getCode());
            // 保存一份临时的原始账单的字典数据列表
            dictListMap.put(linkNoConfig.getBillType().strip(), dictList);
            // 找到英文对应的字段名
            option = dictList.stream().filter(item -> item.getLabel().equals(sourceColumnCn)).findFirst().orElse(null);
            if (option != null) {
                // 可能会漏查数据，因为只查了相邻四个月的关联数据 BUG
                billMonthList = DateUtils.getLastAndNextBillDateList(messageVo.getBillMonth());
                sourceColumnEn = option.getValue().toString().strip();
                // 有字段名称，有表名，就可以拼接sql表达式
                for (String billMonth : billMonthList) {
                    tableNamePrefix = new StringBuilder(sysDictType.getRemark());
                    if (billMonth.length() > 6) {
                        billMonth = billMonth.substring(0, 6);
                    }
                    // 拼接完整表名
                    tableNamePrefix.append(billMonth);
                    // 判断是否已经查询成功
                    sqlText = "select * from " + tableNamePrefix + " where " + sourceColumnEn + " = '" + linkNoValue + "'";
                    mapList = platformSourceDataService.getDataBySql(sqlText, tableNamePrefix.toString());
                    if (Objects.nonNull(mapList) && mapList.size() > 0) {
                        for (Map<String, Object> stringObjectMap : mapList) {
                            dataMap = stringObjectMap;
                            if (Objects.nonNull(dataMap) && dataMap.size() > 0 && Objects.nonNull(dataMap.get("id")) && dataMap.get("id").toString().length() > 0) {
                                for (String key : dataMap.keySet()) {
                                    // 替换空值
                                    if (Objects.isNull(dataMap.get(key))) {
                                        dataMap.put(key, "");
                                    }
                                }
                                tempMapList = sourceTableDataMap.get(linkNoConfig.getBillType());
                                if (Objects.isNull(tempMapList)) {
                                    tempMapList = new ArrayList<>();
                                    tempMapList.add(dataMap);
                                } else {
                                    // 判断前面是否已经查出来，放到集合里面了
                                    String id = dataMap.get("id").toString();
                                    if (tempMapList.stream().noneMatch(item -> Objects.equals(item.get("id").toString(), id))) {
                                        tempMapList.add(dataMap);
                                    }
                                }
                                sourceTableDataMap.put(linkNoConfig.getBillType(), tempMapList);
                                // 这里是查询表明细的sql语句，如果有明细表的话，需要查询出来
                                subTable = tableNamePrefix.toString().replace(billMonth, "") + "detail_" + billMonth;
                                sqlText = "select * from " + subTable + " where order_id = '" + dataMap.get("id").toString() + "'";
                                List<Map<String, Object>> detailMapList = platformSourceDataService.getDataBySql(sqlText, subTable);
                                int size = Objects.isNull(detailMapList) ? 0 : detailMapList.size();
                                for (int j = 0; j < size; j++) {
                                    Map<String, Object> subDataMap = detailMapList.get(j);
                                    // 删除明细的ID
                                    if (Objects.nonNull(subDataMap) && subDataMap.size() > 0 && Objects.nonNull(subDataMap.get("id")) && subDataMap.get("id").toString().length() > 0) {
                                        subDataMap.remove("id");
                                        for (String key : subDataMap.keySet()) {
                                            // 替换空值
                                            if (Objects.isNull(subDataMap.get(key))) {
                                                subDataMap.put(key, "");
                                            }
                                        }
                                        // 将明细数据添加到主数据集
                                        dataMap.putAll(subDataMap);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // 标准账单的字段对应关系
        Map<String, String> standardColumnMap = SysBill.getColumnMap();
        SysBill sysBill = new SysBill();
        // 开始处理转换逻辑
        String dataGeneration;
        String sourceColumn;
        String standardColumn;
        List<SysColumnMatchCondition> conditions;
        String columnValue;
        Field declaredField;
        ResultObj resultObj;
        String standardColumnEN;
        // 基础字段循环赋值
        for (SysBaseColumnMatch baseColumnMatch : sysBaseColumnMatches) {
            if (!SystemConstants.BUSINESS_DATE.equals(baseColumnMatch.getStandardColumn()) && !SystemConstants.LINK_NO.equals(baseColumnMatch.getStandardColumn())) {
                continue;
            }
            // 如果是出账日期，先过滤，后面再获取具体值
            if (SystemConstants.OUT_BILL_DATE.equals(baseColumnMatch.getStandardColumn())) {
                continue;
            }
            dataGeneration = baseColumnMatch.getDataGeneration();
            sourceColumn = baseColumnMatch.getSourceColumn();
            standardColumn = baseColumnMatch.getStandardColumn();
            conditions = baseColumnMatch.getConditions();
            // 通过中文标准账单名称找到英文
            standardColumnEN = standardColumnMap.get(standardColumn);
            if (DataGenerationEnum.DIRECT.getValue().equals(dataGeneration)) {
                // 通过原始账单的字典数据列表，找到原始账单的字段对应的值
                resultObj = new ResultObj();
                getColumnValueFromConfig(sourceTableDataMap, dictListMap, baseColumnMatch.getBillType(), sourceColumn, conditions, resultObj, null);
                if (resultObj.getResultList().size() == 0) {
                    continue;
                }
                // 取其中一条的值作为原始账单的值
                columnValue = resultObj.getResultList().get(0);
                if (StringUtils.hasText(columnValue)) {
                    try {
                        // 判断处理类型
                        if (SysBill.isDate(standardColumnEN)) {
                            declaredField = sysBill.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(sysBill, DateUtils.convertStringToLocalDateTime(columnValue));
                        } else if (SysBill.isDecimal(standardColumnEN)) {
                            declaredField = sysBill.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(sysBill, new BigDecimal(columnValue));
                        } else {
                            declaredField = sysBill.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(sysBill, columnValue);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        // 账单月份
        sysBill.setTableName("sys_bill_%s".formatted(messageVo.getBillMonth()));
        // 关联单号
        sysBill.setLinkNo(StringUtils.replaceStr(linkNoValue, "'", ""));
        // 取出业务日期
        // 通过原始账单配置找到业务日期【系统只允许同一平台只能配置一个业务日期】
        SysBaseColumnMatch baseColumnMatch = sysBaseColumnMatches.stream()
                .filter(item -> SystemConstants.BUSINESS_DATE.equals(item.getStandardColumn().strip())).findFirst().orElse(null);
        if (Objects.isNull(baseColumnMatch)) {
            logger.error("标准账单生成核销单失败：账单配置没有找到【业务日期】配置");
            platformSourceDataService.addNoMatchRecord(messageVo, billType, "账单配置没有找到【业务日期】配置");
            return false;
        }
        boolean containsBusinessDateData = false;
        String sourceDataBillType = baseColumnMatch.getBillType();
        List<Map<String, Object>> maps = sourceTableDataMap.get(sourceDataBillType);
        if (Objects.nonNull(maps) && maps.size() > 0) {
            containsBusinessDateData = true;
        }
        LocalDateTime businessDate = null;
        // 出账日期
        LocalDateTime outBillDate;
        if (containsBusinessDateData) {
            // 通过原始账单配置找到业务日期
            businessDate = getBusinessDateFromSourceTableDataMap(baseColumnMatch, sourceTableDataMap, dictListMap);
            if (Objects.isNull(businessDate)) {
                logger.error("标准账单生成核销单失败：通过账单配置获取【业务日期】失败，下面尝试获取【出账日期】");
            } else {
                // 更新标准账单业务日期为配置有业务日期的原始账单的值
                sysBillService.updateBusinessDate(sysBill.getLinkNo(), businessDate);
            }
        }
        // 查出账单项目配置列表
        List<SysColumnMatch> billProjectConfigList = sysColumnMatchService.getByPlatform(sysPlatform.getPlatformKey() + "bill");
        SysBill projectBill;
        // 可以将【sourceTableDataMap】key为messageVo对应的单据类型的数据列表过滤成一条，减少循环花费的时间
        // 因为上面根据ID查询数据之后，后面还要根据关联单号再查一次，所以会查出一堆历史数据
        // 所以这里可以成过滤【sourceTableDataMap】对应的账单类型的list，过滤条件是【messageVo.dataId】
        Map<String, List<Map<String, Object>>> filterSourceTableDataMap = new HashMap<>();
        sourceTableDataMap.forEach((key, list) -> {
            if (key.equals(billType)) {
                filterSourceTableDataMap.put(key, list.stream().filter(item -> Objects.equals(item.get("id").toString(), messageVo.getDataId())).toList());
            } else {
                filterSourceTableDataMap.put(key, list);
            }
        });
        // 临时变量
        List<LocalDateTime> businessOrOutBillDateList = new ArrayList<>();
        LocalDateTime time;
        SysBaseColumnMatch outBillConfig;
        // 是否可以转换标准账单标识
        boolean canTransferBill = false;
        // 循环账单项目配置
        for (SysColumnMatch sysColumnMatch : billProjectConfigList) {
            resultObj = new ResultObj();
            outBillConfig = sysBaseColumnMatches.stream().filter(item -> Objects.equals(item.getBillType(), sysColumnMatch.getBillType()) && Objects.equals(item.getStandardColumn(), SystemConstants.OUT_BILL_DATE)).findFirst().get();
            getColumnValueFromConfig(filterSourceTableDataMap, dictListMap, sysColumnMatch.getBillType(), sysColumnMatch.getSourceColumn(), sysColumnMatch.getConditionList(), resultObj, outBillConfig.getSourceColumn());
            if (resultObj.getResultList().size() == 0) {
                continue;
            }
            // 可以转换成标准账单标志
            canTransferBill = true;
            if (Objects.equals(sysColumnMatch.getBillCheck(), BillCheckStatusEnum.CHECK.getValue())) {
                // 仅检查配置的判断
                continue;
            }
            // 追加出账日期或者业务日期
            if (resultObj.getOutBillDateList().size() > 0) {
                for (LocalDateTime localDateTime : resultObj.getOutBillDateList()) {
                    time = businessOrOutBillDateList.stream().filter(t -> t.equals(localDateTime)).findFirst().orElse(null);
                    if (time == null) {
                        // 追加不相同的出账日期
                        businessOrOutBillDateList.add(localDateTime);
                    }
                }
            }
            // 这里【resultObj.getResultList()】会返回所有的历史匹配记录数据，然后每条数据生成一条标准账单，再调用equal方法判断是否重复。
            // 20240515 修改为账单不汇总的方式，每个匹配的金额都生成一条独立的标准账单
            BigDecimal billAmount;
            int billMonthIndex = 0;
            String dbId;
            for (String billAmountStr : resultObj.getResultList()) {
                // 对应的数据库表ID
                dbId = resultObj.getResultIdList().get(billMonthIndex);
                // 索引加一 解决生成重复账单，账单ID(pId)一样的问题
                billMonthIndex++;
                // 账单对象
                projectBill = new SysBill();
                BeanUtils.copyProperties(sysBill, projectBill, commonMap.keySet().toArray(new String[0]));
                projectBill.setOriginalBillProject(sysColumnMatch.getOriginalBillProject());
                billAmount = new BigDecimal(billAmountStr);
                // 为0时跳过
                if (billAmount.compareTo(BigDecimal.ZERO) == 0) {
                    continue;
                }
                projectBill.setBillAmount(billAmount);
                outBillDate = getOutBillDateFromSourceTableDataMap(outBillConfig, sourceTableDataMap.get(sysColumnMatch.getBillType()), dictListMap.get(sysColumnMatch.getBillType()), dbId);
                if (Objects.isNull(businessDate)) {
                    projectBill.setBusinessDate(outBillDate);
                } else {
                    projectBill.setBusinessDate(businessDate);
                    // 重新设置账单月份
                    projectBill.setTableName("sys_bill_%s".formatted(DateUtils.formatDate(businessDate)));
                }
                // 等于配置的出账日期
                projectBill.setBillDate(outBillDate);
                // 更新基础字段里面直接取值的配置
                if (commonMap.size() > 0) {
                    CommonItem commonItem;
                    for (String standardEn : commonMap.keySet()) {
                        commonItem = commonMap.get(standardEn);
                        if (!Objects.equals(commonItem.getBillType(), sysColumnMatch.getBillType())) {
                            // 账单类型不相同，代表当前账单项目配置的来源方式不是当前账单类型，跳过
                            continue;
                        }
                        // 设置结算单类型, 后续有其他标准字段需要在这里设置，然后checkAndSave方法里面有隔更新字段的代码，那里也要添加新的标准字段
                        if (Objects.equals("settlementType", standardEn)) {
                            projectBill.setSettlementType(commonItem.getValue());
                        }
                    }
                }
                // 设置唯一标识
                projectBill.setPId(dbId);
                sysBillService.checkAndSave(projectBill, sysStore, sysPlatform, sysColumnMatch.getOriginalBillProject(), commonMap, sysColumnMatch.getBillType());
            }
        }
        // 删除旧的通过计算的账单项目
        List<String> calculateList = sysBaseColumnMatches.stream().filter(item -> DataGenerationEnum.CALCULATE.getValue().equals(item.getDataGeneration())).map(SysBaseColumnMatch::getStandardColumn).toList();
        List<SysBill> allProjectBillList = new ArrayList<>();
        if (calculateList.size() > 0) {
            // 加上linkNo字段非空判断，解决删除数据时，把其他不相关的账单也误删
            if (StringUtils.hasText(sysBill.getLinkNo())) {
                // 查出所有计算类型账单的关联单号保存的账单月份
                List<String> billDateList = sysBillService.getBillMonthListByLinkNo(sysBill.getLinkNo());
                // 取出所有的历史关联的计算类账单
                allProjectBillList = sysBillService.getListByLinkNoAndBillMonth(sysBill.getLinkNo(), billDateList, calculateList);
                // 删除所有历史的计费类型的账单，重新生成
                if (allProjectBillList.size() > 0) {
                    sysBillService.deleteOldRecords(allProjectBillList);
                }
            }
        }
        // 处理通过计算的配置
        // 查找计算类型的相同的电商平台账单项目的对象
        SysBill sameOriginalBillProjectBIll;
        for (SysBaseColumnMatch item : sysBaseColumnMatches) {
            if (DataGenerationEnum.CALCULATE.getValue().equals(item.getDataGeneration())) {
                projectBill = new SysBill();
                BeanUtils.copyProperties(sysBill, projectBill);
                // 根据不同的单据类型，累计原始字段的值
                resultObj = sumColumnValueFromConfig(sourceTableDataMap, dictListMap, item.getCalculateColumnList(), sysBaseColumnMatches);
                projectBill.setBillAmount(resultObj.getTotalAmount());
                // 追加出账日期或者业务日期
                if (resultObj.getOutBillDateList().size() > 0) {
                    for (LocalDateTime localDateTime : resultObj.getOutBillDateList()) {
                        time = businessOrOutBillDateList.stream().filter(t -> t.equals(localDateTime)).findFirst().orElse(null);
                        if (time == null) {
                            // 追加不相同的出账日期
                            businessOrOutBillDateList.add(localDateTime);
                        }
                    }
                }
                // 为 0 时过滤
                if (BigDecimal.ZERO.compareTo(projectBill.getBillAmount()) != 0) {
                    sameOriginalBillProjectBIll = allProjectBillList.stream().filter(record -> Objects.equals(record.getOriginalBillProject(), item.getStandardColumn())).findFirst().orElse(null);
                    // 如果找到相同的电商平台账单项目，则将旧的出账日期赋值给新的账单对象
                    if (Objects.nonNull(sameOriginalBillProjectBIll)) {
                        projectBill.setBillDate(sameOriginalBillProjectBIll.getBillDate());
                    }
                    // 修改为金额等于0时不生成标准订单
                    projectBill.setOriginalBillProject(item.getStandardColumn());
                    if (Objects.nonNull(businessDate)) {
                        projectBill.setBusinessDate(businessDate);
                        // 重新设置账单月份
                        projectBill.setTableName("sys_bill_%s".formatted(DateUtils.formatDate(businessDate)));
                    } else {
                        // 取最晚或者最早的时间作为出账日期
                        projectBill.setBusinessDate(resultObj.getOutBillDate());
                    }
                    if (Objects.isNull(projectBill.getBillDate())) {
                        projectBill.setBillDate(resultObj.getOutBillDate());
                    }
                    // 更新标准账单业务日期为配置有业务日期的原始账单的值
                    if (Objects.nonNull(businessDate)) {
                        sysBillService.updateBusinessDate(projectBill.getLinkNo(), businessDate);
                    }
                    // 如果是【通过计算】的类型 那 标准账单字段 即是 电商平台账单项目
                    sysBillService.saveCalculateBill(projectBill, sysStore, sysPlatform, item.getStandardColumn());
                }
            }
        }
        if (Objects.nonNull(businessDate)) {
            // 如果找到业务日期，则全部以业务日期为准
            businessOrOutBillDateList = new ArrayList<>();
            businessOrOutBillDateList.add(businessDate);
        }
        // 标准账单生成核销单
        if (StringUtils.hasText(sysBill.getLinkNo()) && !businessOrOutBillDateList.isEmpty()) {
            sysAuditService.convert(sysBill.getLinkNo(), businessOrOutBillDateList, sysPlatform, sysStore, Objects.nonNull(businessDate));
        }
        // 检查是否可以生成标准账单
        if (canTransferBill) {
            // 逻辑删除
            if (Objects.nonNull(messageVo.getNoMatchRecordId())) {
                logger.info("转换成功：{}", messageVo);
                platformSourceDataService.deleteNoMatchRecord(messageVo.getNoMatchRecordId());
            }
            // 修改原始账单为转换成功，以便后面失败可以重试
            platformSourceDataService.updateSourceStatus(messageVo.getTableNamePrefix(), messageVo.getBillMonth(), messageVo.getDataId());
        } else {
            // 创建记录
            logger.info("转换标准账单失败，通过账单配置找不到匹配的记录：{}", messageVo);
            platformSourceDataService.addNoMatchRecord(messageVo, billType, null);
        }
        // 返回是否可以转换成功的标记
        return canTransferBill;
    }

    private void omsFunc(MessageVo messageVo) {
        // 先通过标准订单明细字段配置，把OMS订单或者售后单转成标准订单明细，再把标准订单明细以主单号维护汇总生成系统的标准订单汇总（SysOrder）
        // 处理OMS订单
        List<SysOrderDetail> orderDetailList = handleOMSOrder(messageVo.getDataMap(), messageVo.isOmsReturnOrder(), messageVo);
        if (orderDetailList.size() == 0) {
            return;
        }
        // 取第一条作为整个明细的业务日期即可，因为这些明细都是从一条订单或者退货单分割出来的
        LocalDateTime businessDate = orderDetailList.get(0).getBusinessDate();
        // 从数据库中查询所有明细
        List<String> billMonthList = orderDetailList.stream().map(SysOrderDetail::getBillMonth).distinct().toList();
        List<String> mainNoList = orderDetailList.stream().map(SysOrderDetail::getSourceMainNo).distinct().toList();
        // 未分组之前的所有订单明细
        List<SysOrderDetail> noGroupOrderDetailList = new ArrayList<>();
        // 过滤后的所有订单明细
        List<SysOrderDetail> allOrderDetailList = new ArrayList<>();
        // 循环取出订单明细
        SysOrderDetail params;
        for (String billMonth : billMonthList) {
            params = new SysOrderDetail();
            params.setTableName("sys_order_detail_%s".formatted(billMonth));
            params.setMainNoList(mainNoList);
            orderDetailList = sysOrderDetailMapper.getList(params);
            if (orderDetailList.size() > 0) {
                noGroupOrderDetailList.addAll(orderDetailList);
                for (SysOrderDetail orderDetail : orderDetailList) {
                    if (StringUtils.hasText(orderDetail.getFileAuditId())) {
                        continue;
                    }
                    orderDetail.setBillMonth(billMonth);
                    // 设置业务日期，用于生成核销单
                    orderDetail.setBusinessDate(businessDate);
                    allOrderDetailList.add(orderDetail);
                }
            }
        }
        // orderDetailList 通过主单号进行分组合并
        Map<String, List<SysOrderDetail>> collect =
                allOrderDetailList.stream().collect(Collectors.groupingBy(SysOrderDetail::getSourceMainNo));
        // OMS单号如果有多个，合并在一起
        List<SysOrderDetail> groupDataList;
        SysOrderDetail first;
        BigDecimal total;
        int totalQty;
        // 子单号分组合并结果列表
        List<SysOrderDetail> orderDetailNewList = new ArrayList<>();
        for (String sourceMainNo : collect.keySet()) {
            groupDataList = collect.get(sourceMainNo);
            total = BigDecimal.ZERO;
            totalQty = 0;
            first = groupDataList.get(0);
            // OMS单号合并
            first.setOmsNo(noGroupOrderDetailList.stream().filter(item -> Objects.equals(item.getSourceMainNo(), sourceMainNo)).map(SysOrderDetail::getOmsNo).filter(StringUtils::hasText).distinct().collect(Collectors.joining(",")));
            // 原始子单号合并
            first.setSourceSubNo(noGroupOrderDetailList.stream().filter(item -> Objects.equals(item.getSourceMainNo(), sourceMainNo)).map(SysOrderDetail::getSourceSubNo).filter(StringUtils::hasText).distinct().collect(Collectors.joining(",")));
            // 发退货时间   取值标准订单明细中“发退货时间”，有多个值的情况下，取最晚时间
            try {
                first.setOpTime(groupDataList.stream().map(SysOrderDetail::getOpTime).max(LocalDateTime::compareTo).get());
            } catch (Exception ignore) {
            }
            // 统计数量
            for (SysOrderDetail sysOrderDetail : groupDataList) {
                total = total.add(sysOrderDetail.getSendAmount().abs());
                totalQty += Math.abs(sysOrderDetail.getQty());
            }
            // 发货金额 相同主交易号的发货金额相加
            first.setSendAmount(total);
            // 发货数量 相同主交易号的发货数量相加
            first.setQty(totalQty);
            // 置空
            total = BigDecimal.ZERO;
            totalQty = 0;
            // 售后单
            for (SysOrderDetail sysOrderDetail : groupDataList) {
                total = total.add(sysOrderDetail.getReturnAmount().abs());
                totalQty += Math.abs(sysOrderDetail.getReturnQty());
            }
            // 退货金额 相同主交易号的退货金额相加
            first.setReturnAmount(total.negate());
            // 退货数量 相同主交易号的退货数量相加
            first.setReturnQty(-totalQty);
            // 追加到新的列表
            orderDetailNewList.add(first);
        }
        // 循环处理订单明细
        SysStore sysStore;
        SysPlatform sysPlatform;
        // 循环新的列表
        for (SysOrderDetail orderDetail : orderDetailNewList) {
            sysStore = storeService.getById(orderDetail.getStoreId());
            sysPlatform = platformService.getByPlatformKey(sysStore.getStoreKey());
            // 通过标准订单明细生成系统汇总订单（SysOrder）
            SysOrder sysOrder = new SysOrder();
            // 设置业务日期
            sysOrder.setBusinessDate(orderDetail.getBusinessDate());
            // 关联单号
            sysOrder.setLinkNo(orderDetail.getSourceMainNo());
            // 通过业务日期计算出保存到那份表
            sysOrder.setTableName("sys_order_%s".formatted(orderDetail.getBillMonth()));
            // 发货数量
            sysOrder.setQty(orderDetail.getQty());
            // 发货金额
            sysOrder.setSendAmount(orderDetail.getSendAmount());
            // 退货数量
            sysOrder.setReturnQty(-Math.abs(orderDetail.getReturnQty()));
            if (sysOrder.getReturnQty() > 0) {
                sysOrder.setReturnQty(-sysOrder.getReturnQty());
            }
            // 退货金额
            sysOrder.setReturnAmount(orderDetail.getReturnAmount().abs().negate());
            // 发退货时间
            sysOrder.setSendReturnTime(orderDetail.getOpTime());
            // 下单时间
            sysOrder.setOrderTime(orderDetail.getBuyTime());
            // 对账系统店铺编码
            sysOrder.setBillStoreCode(sysStore.getBillSystemStoreCode());
            // 内部系统电商平台编码
            sysOrder.setInnerShopCode(sysStore.getInnerSystemCommercePlatformCode());
            // 电商平台店铺编码
            sysOrder.setPlatformStoreCode(sysStore.getCommercePlatformStoreCode());
            // 内部系统店铺编码
            sysOrder.setShopCode(sysStore.getInnerSystemStoreCode());
            // 财务系统店铺编码
            sysOrder.setBillSysStore(sysStore.getFinanceSystemStoreCode());
            // 所属平台
            sysOrder.setPlatform(sysPlatform.getPlatformKey());
            // 所属店铺
            sysOrder.setStoreId(orderDetail.getStoreId());
            // 商品单价
            sysOrder.setPrice(orderDetail.getPrice());
            // 原始主订单号
            sysOrder.setSourcePreformMainNo(orderDetail.getSourceMainNo());
            // 原始子订单号
            sysOrder.setSourcePreformSubNo(orderDetail.getSourceSubNo());
            sysOrder.setLinkNo(StringUtils.replaceStr(sysOrder.getLinkNo(), "'", ""));
            // 订单状态
            sysOrder.setOrderStatus(orderDetail.getOrderStatus());
            // OMS单号
            sysOrder.setOmsNo(orderDetail.getOmsNo());
            // 如果各项金额或者数字都为0，则不生成标准订单汇总
            if (sysOrder.isAllZero()) {
                continue;
            }
            // 保存或者更新标准订单
            sysOrder = sysOrderService.insertOrUpdate(sysOrder, messageVo.isOmsReturnOrder());
            // 标准订单生成核销单
            if (Objects.nonNull(sysOrder.getLinkNo())) {
                sysAuditService.convert(sysOrder, sysPlatform, sysStore);
            }
        }
    }

    /**
     * 先通过标准订单明细字段配置，把OMS订单或者售后单转成标准订单明细，再把标准订单明细以主单号维护汇总生成系统的标准订单汇总（SysOrder）
     *
     * @param omsDataMap       OMS订单数据详情
     * @param isOmsReturnOrder 是否是售后单
     * @param messageVo        消息队列对象
     * @return SysOrderDetail 生成的标准订单明细
     */
    private List<SysOrderDetail> handleOMSOrder(Map<String, String> omsDataMap, boolean isOmsReturnOrder, MessageVo messageVo) {
        // 生成的标准订单明细（这里可能会生成多行订单明细）
        List<SysOrderDetail> sysOrderDetailList = new ArrayList<>();
        SysStore sysStore = storeService.getById(messageVo.getStoreId());
        // 去除空格
        omsDataMap.forEach((k, v) -> {
            if (v != null) {
                omsDataMap.put(k, v.strip());
            }
        });
        SysOrderDetail sysOrderDetail;
        // 判断是OMS订单还是OMS售后单
        if (!isOmsReturnOrder) {
            // 下单月份（按照下单时间分表）
            // 通过配置获取账单月份对应的原始字段，再通过反射获取值
            // 通过配置获取账单月份【billMonth】
            List<SysBaseColumnMatch> configListByPlatform = sysBaseColumnMatchService.getBusinessConfigListByPlatform(SystemConstants.OMS_ORDER_DICT_KEY, null);
            if (configListByPlatform.size() == 0) {
                logger.error("未配置OMS订单【业务日期】字段配置");
                return sysOrderDetailList;
            }
            String sourceColumn = configListByPlatform.get(0).getSourceColumn();
            String sourceColumnEn = BsOmsOrderImportVo.getKeyMap().get(sourceColumn);
            // 直接从Map中取值
            String billMonth = DateUtils.formatDate(DateUtils.convertStringToLocalDateTime(omsDataMap.get(sourceColumnEn)));
            if (Objects.isNull(billMonth)) {
                logger.error("OMS订单【业务日期】字段值转换错误");
                return sysOrderDetailList;
            }
            // 通过平台找到OMS原始订单转标准订单明细的配置
            List<SysBaseColumnMatch> sysBaseColumnMatches = sysBaseColumnMatchService.getByPlatform(SystemConstants.OMS_ORDER_DICT_KEY);
            // 这里需要分情况，【原始主订单号】有没有合并，如果没有合并，就直接生成一条订单明细，如果出现合并，就生成多行订单明细
            // 先处理没有合并的情况，通过配置获取原始主订单号对应的原始字段
            if (sysBaseColumnMatches.size() == 0) {
                logger.error("【%s】没有配置原始字段对应关系".formatted(SystemConstants.OMS_ORDER_DICT_KEY));
                return sysOrderDetailList;
            }
            // 通过切割PID获取原始订单ID
            String linkId = omsDataMap.get("pId").split("-")[0];
            sysOrderDetail = transferOMSOrder2OrderDetail(omsDataMap, sysBaseColumnMatches, BsOmsOrderImportVo.getKeyMap(), SysOrderDetailImportVo.getKeyMap());
            // 关联原始主表的ID
            sysOrderDetail.setLinkId(linkId);
            // 店铺
            sysOrderDetail.setStoreId(sysStore.getId());
            this.checkAndAddToList(sysOrderDetail, billMonth, sysStore, sysOrderDetailList);
            return sysOrderDetailList;
        } else {
            // 售后单
            // 通过配置获取账单月份【billMonth】
            List<SysBaseColumnMatch> configListByPlatform = sysBaseColumnMatchService.getBusinessConfigListByPlatform(SystemConstants.OMS_RETURN_ORDER_DICT_KEY, null);
            if (configListByPlatform.size() == 0) {
                logger.error("【%s】没有配置【业务日期】".formatted(SystemConstants.OMS_RETURN_ORDER_DICT_KEY));
                return sysOrderDetailList;
            }
            // 配置的账单月份
            String sourceColumn = configListByPlatform.get(0).getSourceColumn();
            String sourceColumnEn = BsOmsReturnOrderImportVo.getKeyMap().get(sourceColumn);
            // 直接从Map中取值
            String billMonth = DateUtils.formatDate(DateUtils.convertStringToLocalDateTime(omsDataMap.get(sourceColumnEn)));
            if (Objects.isNull(billMonth)) {
                return sysOrderDetailList;
            }
            // 转换成标准订单明细
            // 通过平台找到OMS原始订单转标准订单明细的配置
            List<SysBaseColumnMatch> sysBaseColumnMatches = sysBaseColumnMatchService.getByPlatform(SystemConstants.OMS_RETURN_ORDER_DICT_KEY);
            if (sysBaseColumnMatches.size() == 0) {
                logger.error("【%s】没有配置原始字段对应关系".formatted(SystemConstants.OMS_RETURN_ORDER_DICT_KEY));
                return sysOrderDetailList;
            }
            // 通过切割PID获取原始订单ID
            String linkId = omsDataMap.get("pId").split("-")[0];
            sysOrderDetail = transferOMSOrder2OrderDetail(omsDataMap, sysBaseColumnMatches, BsOmsReturnOrderImportVo.getKeyMap(), SysOrderDetailImportVo.getKeyMap());
            // 关联原始主表的ID
            sysOrderDetail.setLinkId(linkId);
            // 店铺
            sysOrderDetail.setStoreId(sysStore.getId());
            this.checkAndAddToList(sysOrderDetail, billMonth, sysStore, sysOrderDetailList);
            return sysOrderDetailList;
        }
    }

    private void checkAndAddToList(SysOrderDetail sysOrderDetail, String billMonth, SysStore sysStore, List<SysOrderDetail> sysOrderDetailList) {
        sysOrderDetail.setId(snowflakeIdWorker.nextId(billMonth));
        // 店铺
        sysOrderDetail.setStoreId(sysStore.getId());
        if (!StringUtils.hasText(sysOrderDetailMapper.existTable(sysOrderDetail.getTableName()))) {
            // 创建表格
            sysOrderDetailMapper.createTable(sysOrderDetail.getTableName());
            // 删除缓存
            redisTemplate.delete(SystemConstants.ORDER_DETAIL_KEY);
        }
        // 按照子单号进行合并
        SysOrderDetail params = new SysOrderDetail();
        params.setTableName(sysOrderDetail.getTableName());
        params.setStoreId(sysStore.getId());
        params.setSourceSubNo(sysOrderDetail.getSourceSubNo());
        List<SysOrderDetail> orderDetails = sysOrderDetailMapper.getList(params);
        if (orderDetails.size() > 0) {
            SysOrderDetail sameDetail = orderDetails.stream().filter(item -> item.equals(sysOrderDetail)).findFirst().orElse(null);
            if (Objects.isNull(sameDetail)) {
                if (!sysOrderDetail.isAllZero()) {
                    // 保存
                    sysOrderDetailMapper.insertData(sysOrderDetail);
                    // 加入列表
                    sysOrderDetailList.add(sysOrderDetail);
                }
            } else {
                sameDetail.setTableName(sysOrderDetail.getTableName());
                // 追加数量
                sameDetail.setQty(sameDetail.getQty() + sysOrderDetail.getQty());
                // 追加发货金额
                sameDetail.setSendAmount(sameDetail.getSendAmount().add(sysOrderDetail.getSendAmount()));
                // OMS单号
                if (!StringUtils.hasText(sameDetail.getOmsNo())) {
                    sameDetail.setOmsNo(sysOrderDetail.getOmsNo());
                }
                // 发退货时间
                if (Objects.isNull(sameDetail.getOpTime())) {
                    sameDetail.setOpTime(sysOrderDetail.getOpTime());
                }
                // 下单时间
                if (Objects.isNull(sameDetail.getBuyTime())) {
                    sameDetail.setBuyTime(sysOrderDetail.getBuyTime());
                }
                // PO单号
                if (!StringUtils.hasText(sameDetail.getPoNo())) {
                    sameDetail.setPoNo(sysOrderDetail.getPoNo());
                }
                // 商品单价
                if (sameDetail.getPrice().compareTo(BigDecimal.ZERO) == 0) {
                    sameDetail.setPrice(sysOrderDetail.getPrice());
                }
                // 品牌
                if (!StringUtils.hasText(sameDetail.getBrand())) {
                    sameDetail.setBrand(sysOrderDetail.getBrand());
                }
                // SKU
                if (!StringUtils.hasText(sameDetail.getSku())) {
                    sameDetail.setSku(sysOrderDetail.getSku());
                }
                // 商品名称
                if (!StringUtils.hasText(sameDetail.getProductName())) {
                    sameDetail.setProductName(sysOrderDetail.getProductName());
                }
                // 订单状态
                if (!StringUtils.hasText(sameDetail.getOrderStatus())) {
                    sameDetail.setOrderStatus(sysOrderDetail.getOrderStatus());
                }
                if (!sameDetail.isAllZero()) {
                    // 保存
                    sysOrderDetailMapper.update(sameDetail);
                    // 账单月份
                    sameDetail.setBillMonth(sameDetail.getId().substring(0, 6));
                    // 加入列表
                    sysOrderDetailList.add(sameDetail);
                }
            }

        } else {
            if (!sysOrderDetail.isAllZero()) {
                // 保存
                sysOrderDetailMapper.insertData(sysOrderDetail);
                // 加入列表
                sysOrderDetailList.add(sysOrderDetail);
            }
        }
    }

    /**
     * 转换OMS销售订单为标准订单明细 网店交易号没有合并的情况
     *
     * @param originalOmsOrder          OMS销售订单
     * @param sysBaseColumnMatches      OMS单据字段配置
     * @param originalOmsOrderColumnMap OMS销售订单字段
     * @param orderDetailColumnMap      标准订单明细字段
     * @return 生成的标准订单明细
     */
    private SysOrderDetail transferOMSOrder2OrderDetail(Map<String, String> originalOmsOrder, List<SysBaseColumnMatch> sysBaseColumnMatches, Map<String, String> originalOmsOrderColumnMap, Map<String, String> orderDetailColumnMap) {
        SysOrderDetail detail = new SysOrderDetail();
        // 循环字段配置
        String sourceColumn;
        String sourceColumnValue;
        String standardColumnCn;
        String conditions;
        String params;
        // 是否通过条件判断
        boolean isValid;
        String sourceColumnEN;
        String standardColumnEN;
        Field declaredField;
        for (SysBaseColumnMatch sysBaseColumnMatch : sysBaseColumnMatches) {
            sourceColumn = sysBaseColumnMatch.getSourceColumn();
            standardColumnCn = sysBaseColumnMatch.getStandardColumn();
            // 检查是否有符合条件
            /**
             * 注意：这里不考虑数据生成方式为【通过计算】的逻辑，因为订单配置没有相加或者相减的逻辑，只有一一对应
             */
            isValid = false;
            if (sysBaseColumnMatch.getConditions() != null && sysBaseColumnMatch.getConditions().size() > 0) {
                for (SysColumnMatchCondition condition : sysBaseColumnMatch.getConditions()) {
                    conditions = condition.getConditions();
                    params = condition.getParams();
                    // 检查条件是否合法
                    isValid = checkIsValid(conditions, params, originalOmsOrder, originalOmsOrderColumnMap);
                    if (!isValid) {
                        // 如果出现其中一个条件不合法，则跳出循环
                        break;
                    }
                }
            } else {
                // 如果没有条件，则代表合法
                isValid = true;
            }
            if (isValid) {
                // 通过原始字段找到数据库的属性，再通过反射获取值
                sourceColumnEN = originalOmsOrderColumnMap.get(sourceColumn);
                if (Objects.nonNull(sourceColumnEN)) {
                    try {
                        sourceColumnValue = originalOmsOrder.get(sourceColumnEN);
                        // 再通过标准订单明细配置，找到数据库字段
                        standardColumnEN = orderDetailColumnMap.get(standardColumnCn);
                        // 判断处理类型
                        if (SysOrderDetail.isDate(standardColumnEN)) {
                            declaredField = detail.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(detail, DateUtils.convertStringToLocalDateTime(sourceColumnValue));
                        } else if (SysOrderDetail.isDecimal(standardColumnEN)) {
                            declaredField = detail.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(detail, new BigDecimal(sourceColumnValue));
                        } else if (SysOrderDetail.isInteger(standardColumnEN)) {
                            declaredField = detail.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(detail, Integer.valueOf(sourceColumnValue));
                        } else {
                            declaredField = detail.getClass().getDeclaredField(standardColumnEN);
                            declaredField.setAccessible(true);
                            declaredField.set(detail, sourceColumnValue);
                        }
                    } catch (Exception exception) {
                        logger.error("原始字段【%s】转换错误：%s".formatted(sourceColumn, exception.getMessage()));
                    }
                }
            }
        }
        // 账单月份
        detail.setBillMonth(DateUtils.formatDate(detail.getBusinessDate()));
        if (Objects.nonNull(detail.getBillMonth())) {
            detail.setTableName("sys_order_detail_%s".formatted(detail.getBillMonth()));
        }
        return detail;
    }

    // 通过Ognl表达式判断是否通过条件
    private boolean checkIsValid(String conditions, String params, Map<String, String> originalOmsOrder, Map<String, String> originalOmsOrderColumnMap) {
        Map<String, Object> context = new HashMap<>();
        // 通过反射获取值
        params = params.replaceAll("，", ",");
        String columnEn;
        Field declaredField;
        String sourceColumnValue;
        for (String param : params.split(",")) {
            if (!StringUtils.hasText(param.strip())) {
                continue;
            }
            try {
                columnEn = originalOmsOrderColumnMap.get(param.strip());
                declaredField = originalOmsOrder.getClass().getDeclaredField(columnEn);
                declaredField.setAccessible(true);
                sourceColumnValue = declaredField.get(originalOmsOrder).toString();
                context.put(param, sourceColumnValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            return (Boolean) Ognl.getValue(conditions.replaceAll("”", "\""), context);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 通过Ognl表达式判断是否通过条件
    private void checkIsValid(String conditions, String params, Map<String, List<Map<String, Object>>> sourceTableDataMap, Map<String, List<Option>> dictListMap, ResultObj resultObj, String targetTableName, Option targetOption, List<Option> optionList, String outBillCn) {
        // 通过反射获取值
        params = params.replaceAll("，", ",");
        String tableName;
        /**
         * 先通过参数切割出涉及到的表名，然后获取表名对应的数据库对象列表，然后各种组合，比如涉及两个表，每个表有两条数据，那组合后就是有4种组合情况
         * 涉及3个表，每个表有2条数据，那组合后就是有6种组合情况，以此类推
         */
        // 把所有表名对应的数据列表添加到一个总的列表里面
        List<List<String>> allTableIdListList = new ArrayList<>();
        List<Map<String, Object>> dbDataMapList;
        int index = 0;
        String tableId;
        List<String> tableIdList;
        for (String tName : sourceTableDataMap.keySet()) {
            tableIdList = new ArrayList<>();
            dbDataMapList = sourceTableDataMap.get(tName);
            // 过滤不需要条件判断的原数据
            if (!params.contains(tName)) {
                continue;
            }
            for (Map<String, Object> stringObjectMap : dbDataMapList) {
                // 先缓存一个临时变量（表名）
                stringObjectMap.put("tableName", tName);
                tableId = "%sTB%s".formatted(tName, index);
                stringObjectMap.put("tableNameId", tableId);
                tableIdList.add(tableId);
                index++;
            }
            if (tableIdList.size() > 0) {
                allTableIdListList.add(tableIdList);
            }
        }
        // 这里就需要做笛卡尔积
        List<String> result = new ArrayList<>(); // 所有组合情况
        generatePermutations(allTableIdListList, result, 0, "");
        // 循环所有组合情况
        List<Map<String, Object>> groupMapDataList;
        Map<String, Object> mapDataItem;
        Map<String, Map<String, Object>> sourceTableMapMap;
        for (String groupText : result) {
            // 按照冒号拆分
            groupMapDataList = new ArrayList<>();
            for (String tId : groupText.split(":")) {
                mapDataItem = getMapDataByTableId(sourceTableDataMap, tId);
                if (Objects.nonNull(mapDataItem)) {
                    groupMapDataList.add(mapDataItem);
                }
            }
            // 再转换成Map key = 表名 value = 数据库数据字典
            sourceTableMapMap = new HashMap<>();
            for (Map<String, Object> stringObjectMap : groupMapDataList) {
                tableName = (String) stringObjectMap.get("tableName");
                sourceTableMapMap.put(tableName, stringObjectMap);
            }
            // 循环处理每一种组合情况，发现其中一组数据符合条件，就返回true
            checkIsValidFunc(conditions, params, sourceTableMapMap, dictListMap, resultObj, targetTableName, targetOption, optionList, outBillCn);
        }
    }

    // 通过Ognl表达式判断是否通过条件
    private void checkIsValidFunc(String conditions, String params, Map<String, Map<String, Object>> sourceTableDataMap, Map<String, List<Option>> dictListMap, ResultObj resultObj, String targetTableName, Option targetOption, List<Option> billTypeOptionList, String outBillCn) {
        Map<String, Object> context = new HashMap<>();
        // 通过反射获取值
        params = params.replaceAll("，", ",");
        String[] strings;
        String tableName;
        List<Option> optionList;
        Option option;
        String dbValue = "";
        Map<String, Object> sourceTableData;
        for (String param : params.split(",")) {
            if (!StringUtils.hasText(param) || param.strip().length() == 0) {
                continue;
            }
            conditions = conditions.replace(param, param.replace("/", ""));
        }
        for (String param : params.split(",")) {
            try {
                if (!StringUtils.hasText(param.strip())) {
                    continue;
                }
                strings = param.split("的", 2);
                tableName = strings[0].strip();
                String tableFieldCn = strings[1].strip();
                optionList = dictListMap.get(tableName);
                option = optionList.stream().filter(item -> item.getLabel().equals(tableFieldCn))
                        .findFirst()
                        .orElse(null);
                if (Objects.isNull(option)) {
                    return;
                }
                sourceTableData = sourceTableDataMap.get(tableName);
                if (Objects.isNull(sourceTableData)) {
                    continue;
                }
                if (Objects.nonNull(sourceTableData.get(option.getValue()))) {
                    dbValue = sourceTableData.get(option.getValue()).toString();
                }
                context.put(param.strip().replaceAll("/", ""), dbValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            if (context.isEmpty()) {
                return;
            }
            boolean isValid = (Boolean) Ognl.getValue(conditions.strip().replaceAll("“", "\"").replaceAll("”", "\""), context);
            if (isValid) {
                // 找到原始值
                Object obj = sourceTableDataMap.get(targetTableName).get(targetOption.getValue());
                if (Objects.nonNull(obj)) {
                    // 追加金额
                    resultObj.getResultList().add(obj.toString());
                    // 追加数据库ID
                    resultObj.getResultIdList().add(sourceTableDataMap.get(targetTableName).get("id").toString());
                    if (Objects.isNull(outBillCn)) {
                        return;
                    }
                    // 找到出账日期的配置(可能没有)
                    Option outBillDateOption = billTypeOptionList.stream().filter(item -> Objects.equals(outBillCn, item.getLabel()))
                            .findFirst()
                            .orElse(null);
                    if (Objects.nonNull(outBillDateOption)) {
                        LocalDateTime time = DateUtils.convertStringToLocalDateTime(sourceTableDataMap.get(targetTableName).get(outBillDateOption.getValue().toString()).toString());
                        resultObj.setOutBillDate(time);
                        resultObj.getOutBillDateList().add(time);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Map<String, Object> getMapDataByTableId(Map<String, List<Map<String, Object>>> sourceTableDataMap, String tId) {
        for (String billType : sourceTableDataMap.keySet()) {
            for (Map<String, Object> stringObjectMap : sourceTableDataMap.get(billType)) {
                if (Objects.isNull(stringObjectMap)) {
                    continue;
                }
                if (Objects.equals(stringObjectMap.get("tableNameId"), tId)) {
                    return stringObjectMap;
                }
            }
        }
        return null;
    }

    private static void generatePermutations(List<List<String>> allTableDataListList, List<String> result, int depth, String current) {
        if (depth == allTableDataListList.size()) {
            result.add(current);
            return;
        }
        for (int i = 0; i < allTableDataListList.get(depth).size(); i++) {
            generatePermutations(allTableDataListList, result, depth + 1, current + ":" + allTableDataListList.get(depth).get(i));
        }
    }

    @Data
    public static class ResultObj {
        // 存储对应的金额列表对象
        private List<String> resultList = new ArrayList<>();
        // 存储对应的数据库金额对应的ID列表对象
        private List<String> resultIdList = new ArrayList<>();
        // 金额总数
        private BigDecimal totalAmount = BigDecimal.ZERO;
        // 最晚或者最早出账时间
        private LocalDateTime outBillDate;
        // 所有的出账日期
        private List<LocalDateTime> outBillDateList = new ArrayList<>();
    }


    @Data
    public static class MainSubNoObj {
        private String mainNo;
        private String subNo;
    }

    @Data
    public static class CommonItem {
        private String billType;
        private String value;
    }
}
